package org.example.ims.Service.Order.Impl;

import jakarta.persistence.criteria.Predicate;
import org.example.ims.DTO.StockInOutDTO;
import org.example.ims.Entity.Base.Product;
import org.example.ims.Entity.Base.Salesman;
import org.example.ims.Entity.Base.Warehouse;
import org.example.ims.Entity.Order.InStockDetail;
import org.example.ims.Entity.Order.InStockOrder;
import org.example.ims.Repository.Order.InStockOrderRepository;
import org.example.ims.Service.Base.SalesmanService;
import org.example.ims.Service.Base.SupplierService;
import org.example.ims.Service.Base.WarehouseService;
import org.example.ims.Service.Order.InStockDetailService;
import org.example.ims.Service.Order.InStockOrderService;
import org.example.ims.Service.WarehouseProduct.WarehouseProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

@Service("inStockOrderService")
public class InStockOrderServiceImpl implements InStockOrderService {

    @Autowired
    private  InStockOrderRepository orderRepository;
    @Autowired
    private InStockDetailService inStockDetailService;
    @Autowired
    private SupplierService supplierService;
    @Autowired
    private SalesmanService salesmanService;
    @Autowired
    private WarehouseService warehouseService;
    @Autowired
    private WarehouseProductService warehouseProductService;


    @Override
    public InStockOrder createOrder(InStockOrder order) {
        for (InStockDetail detail : order.getDetails()) {
            detail.setOrder(order); // 手动设置外键
        }
        return orderRepository.save(order);
    }

    @Override
    public InStockOrder updateOrder(Integer orderId, InStockOrder updatedOrder) {
        InStockOrder existingOrder = orderRepository.findById(orderId)
                .orElseThrow(() -> new NoSuchElementException("InStockOrder not found with id: " + orderId));
        // 清除旧的details
        existingOrder.getDetails().clear();
        // 添加新的details
        for (InStockDetail detail : updatedOrder.getDetails()) {
            detail.setOrder(existingOrder); // 确保设置新的order
            existingOrder.getDetails().add(detail);
        }
        // 保存更新后的order
        return orderRepository.save(existingOrder);

    }

    @Override
    public void deleteOrder(Integer orderId) {
        if (!orderRepository.existsById(orderId)) {
            throw new NoSuchElementException("InStockOrder does not exist with id: " + orderId);
        }
        orderRepository.deleteById(orderId);
    }

    @Override
    public InStockOrder getOrderById(Integer orderId) {
        return orderRepository.findById(orderId)
                .orElseThrow(() -> new NoSuchElementException("InStockOrder not found with id: " + orderId));
    }

    @Override
    public Page<InStockOrder> getAllOrders(Integer page, Integer size) {
        return orderRepository.findAll(PageRequest.of(page, size));
    }


    @Override
    public Page<InStockOrder> searchOrders(String status,
                                    Integer supplierId, Integer salesmanId, Integer warehouseId,
                                    Integer page, Integer size){
        Specification<InStockOrder>  specification=  buildSpecification(status,supplierId,salesmanId,warehouseId);
        return orderRepository.findAll(specification,PageRequest.of(page, size));
    }

    @Override
    public void executeOrder(Integer orderId) {
        try {
            // 根据订单ID获取订单信息，如果不存在则抛出异常
            InStockOrder order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new NoSuchElementException("InStockOrder not found with id: " + orderId));

            // 执行订单有效性验证和库存可行性检查
            // 1. 验证订单相关实体（如仓库）的有效性
            Warehouse warehouse = validateRelatedEntities(order);

            // 2. 验证库存可行性，并获取入库详细信息
            //    传入订单详情和仓库信息，检查产品库存是否满足要求
            StockInOutDTO<Product> inStockDTO = inStockDetailService.validityAssessment(order.getDetails(), warehouse);

            // 执行入库操作
            warehouseProductService.stockIn(warehouse, inStockDTO);

            // 更新订单状态为已完成
            order.setStatus("completed");
            orderRepository.save(order);

        } catch (Exception e) {
            // 重新获取订单对象,更改订单状态
            InStockOrder order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new NoSuchElementException("InStockOrder not found with id: " + orderId));
            order.setStatus("failed");
            orderRepository.save(order);
            throw new RuntimeException (e.getMessage());
        }
    }



    // Build a specification for searching orders
    private Specification<InStockOrder> buildSpecification(String status,
                                                           Integer supplierId,
                                                           Integer salesmanId,
                                                           Integer warehouseId) {
        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (status != null) {
                predicates.add(cb.equal(root.get("status"), status));
            }
            if (supplierId != null) {
                predicates.add(cb.equal(root.get("supplier").get("id"), supplierId));
            }
            if (salesmanId != null) {
                predicates.add(cb.equal(root.get("salesman").get("id"), salesmanId));
            }
            if (warehouseId != null) {
                predicates.add(cb.equal(root.get("warehouse").get("id"), warehouseId));
            }

            return cb.and(predicates.toArray(new Predicate[0]));
        };
    }

    // Validate related entities
    private Warehouse validateRelatedEntities(InStockOrder order) {

        //判断业务员信息
        if (order.getSalesmanId() != null ) {
            Optional<Salesman> salesman = salesmanService.getSalesmanById(order.getSalesmanId());
            if (salesman.isEmpty()) {
                throw new NoSuchElementException("Salesman not found with id: " + order.getSupplierId());
            }
        }
        //判断仓库信息，核心判断
        if (order.getWarehouseId() != null ) {
            Optional<Warehouse> warehouse = warehouseService.findWarehouseById(order.getWarehouseId());
            if (warehouse.isEmpty()) {
                throw new NoSuchElementException("Salesman not found with id: " + order.getWarehouseId());
            }
            return warehouse.get();
        }
        return null;
    }
}